{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "639f4dc5f1af1901",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-17T11:37:03.015589Z",
     "start_time": "2024-02-17T11:37:03.008923Z"
    },
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[  MainThread ] 查询车次信息\n"
     ]
    }
   ],
   "source": [
    "import httpx\n",
    "import orjson\n",
    "\n",
    "# 定义变量\n",
    "import pandas as pd\n",
    "\n",
    "pd.set_option(\"display.max_columns\", None)\n",
    "pd.set_option(\"display.max_rows\", None)\n",
    "pd.set_option(\"max_colwidth\", 1000)\n",
    "\n",
    "# 起始站-终点站,日期,车次\n",
    "station_start = \"赣榆\"\n",
    "station_end = \"上海虹桥\"\n",
    "date = \"2024-02-23\"\n",
    "filter_train_names = [\"D2145\"]\n",
    "\n",
    "print(\"查询车次信息\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "8c675565c1d362fc",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-17T11:37:06.999555Z",
     "start_time": "2024-02-17T11:37:06.987877Z"
    },
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def query_booking_by_station_v3_for_pc(\n",
    "    station_start: str, station_end: str, date: str\n",
    ") -> list:\n",
    "    response = httpx.post(\n",
    "        \"https://m.suanya.com/restapi/soa2/14666/json/GetBookingByStationV3ForPC\",\n",
    "        headers={\n",
    "            \"authority\": \"m.suanya.com\",\n",
    "            \"accept\": \"*/*\",\n",
    "            \"accept-language\": \"zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6\",\n",
    "            \"cache-control\": \"max-age=0\",\n",
    "            \"content-type\": \"application/x-www-form-urlencoded; charset=UTF-8\",\n",
    "            \"if-modified-since\": \"Thu, 01 Jan 1970 00:00:00 GMT\",\n",
    "            \"origin\": \"https://www.suanya.com\",\n",
    "            \"referer\": \"https://www.suanya.com/\",\n",
    "            \"sec-ch-ua\": '\"Not A(Brand\";v=\"99\", \"Microsoft Edge\";v=\"121\", \"Chromium\";v=\"121\"',\n",
    "            \"sec-ch-ua-mobile\": \"?0\",\n",
    "            \"sec-ch-ua-platform\": '\"Windows\"',\n",
    "            \"sec-fetch-dest\": \"empty\",\n",
    "            \"sec-fetch-mode\": \"cors\",\n",
    "            \"sec-fetch-site\": \"same-site\",\n",
    "        },\n",
    "        data={\n",
    "            \"ArriveStation\": station_end,\n",
    "            \"ChannelName\": \"ctrip.pc\",\n",
    "            \"DepartDate\": date,\n",
    "            \"DepartStation\": station_start,\n",
    "        },\n",
    "    )\n",
    "    text = response.text\n",
    "    data = orjson.loads(text)\n",
    "    TrainItems = data[\"ResponseBody\"][\"TrainItems\"]\n",
    "    return TrainItems\n",
    "\n",
    "\n",
    "def query_booking_by_station_v3_for_pc_async(\n",
    "    station_start: str, station_end: str, date: str\n",
    ") -> list:\n",
    "    query_booking_by_station_v3_for_pc(station_start, station_end, date)\n",
    "\n",
    "\n",
    "def transform_booking_train_items_info_to_dataframe(train_items: list):\n",
    "    # 定义列名的中英文对照字典\n",
    "    columns_chinese = {\n",
    "        \"train_number\": \"车次\",\n",
    "        \"start_time\": \"开始时间\",\n",
    "        \"end_time\": \"结束时间\",\n",
    "        \"duration\": \"耗时\",\n",
    "        \"first_class_price\": \"一等座价格\",\n",
    "        \"first_class_seats\": \"一等座余票量\",\n",
    "        \"second_class_price\": \"二等座价格\",\n",
    "        \"second_class_seats\": \"二等座余票量\",\n",
    "    }\n",
    "\n",
    "    # 使用英文列名创建DataFrame\n",
    "    data = [\n",
    "        {\n",
    "            \"train_number\": item[\"TrainName\"],\n",
    "            \"start_time\": item[\"StartTime\"],\n",
    "            \"end_time\": item[\"EndTime\"],\n",
    "            \"duration\": f'{item[\"UseTime\"] // 60}小时{item[\"UseTime\"] % 60}分钟',\n",
    "            \"first_class_price\": next(\n",
    "                (\n",
    "                    ticket[\"Price\"]\n",
    "                    for ticket in item[\"TicketResult\"][\"TicketItems\"]\n",
    "                    if ticket[\"SeatTypeName\"] == \"一等座\"\n",
    "                ),\n",
    "                None,\n",
    "            ),\n",
    "            \"first_class_seats\": next(\n",
    "                (\n",
    "                    ticket[\"Inventory\"]\n",
    "                    for ticket in item[\"TicketResult\"][\"TicketItems\"]\n",
    "                    if ticket[\"SeatTypeName\"] == \"一等座\"\n",
    "                ),\n",
    "                None,\n",
    "            ),\n",
    "            \"second_class_price\": next(\n",
    "                (\n",
    "                    ticket[\"Price\"]\n",
    "                    for ticket in item[\"TicketResult\"][\"TicketItems\"]\n",
    "                    if ticket[\"SeatTypeName\"] == \"二等座\"\n",
    "                ),\n",
    "                None,\n",
    "            ),\n",
    "            \"second_class_seats\": next(\n",
    "                (\n",
    "                    ticket[\"Inventory\"]\n",
    "                    for ticket in item[\"TicketResult\"][\"TicketItems\"]\n",
    "                    if ticket[\"SeatTypeName\"] == \"二等座\"\n",
    "                ),\n",
    "                None,\n",
    "            ),\n",
    "        }\n",
    "        for item in train_items\n",
    "    ]\n",
    "\n",
    "    train_list = pd.DataFrame(data)\n",
    "    # 重命名列名 , 不会改变原来的列名\n",
    "    return train_list.rename(columns=columns_chinese)\n",
    "\n",
    "\n",
    "def query_stop_station_list(\n",
    "    train_name: str, date: str, start_station: str, end_station: str\n",
    ") -> list:\n",
    "    start_end_ret = httpx.post(\n",
    "        \"https://m.suanya.com/restapi/soa2/14666/json/GetTrainStopListV3\",\n",
    "        headers={\n",
    "            \"authority\": \"m.suanya.com\",\n",
    "            \"accept\": \"*/*\",\n",
    "            \"accept-language\": \"zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6\",\n",
    "            \"cache-control\": \"max-age=0\",\n",
    "            \"content-type\": \"application/x-www-form-urlencoded; charset=UTF-8\",\n",
    "            \"if-modified-since\": \"Thu, 01 Jan 1970 00:00:00 GMT\",\n",
    "            \"origin\": \"https://www.suanya.com\",\n",
    "            \"referer\": \"https://www.suanya.com/\",\n",
    "            \"sec-ch-ua\": '\"Not A(Brand\";v=\"99\", \"Microsoft Edge\";v=\"121\", \"Chromium\";v=\"121\"',\n",
    "            \"sec-ch-ua-mobile\": \"?0\",\n",
    "            \"sec-ch-ua-platform\": '\"Windows\"',\n",
    "            \"sec-fetch-dest\": \"empty\",\n",
    "            \"sec-fetch-mode\": \"cors\",\n",
    "            \"sec-fetch-site\": \"same-site\",\n",
    "        },\n",
    "        data={\n",
    "            \"TrainName\": train_name,\n",
    "            \"DepartStation\": start_station,\n",
    "            \"ArrStation\": end_station,\n",
    "            \"DepartureDate\": date,\n",
    "        },\n",
    "    )\n",
    "    text = start_end_ret.text\n",
    "    data = orjson.loads(text)\n",
    "    train_stop_list = data[\"TrainStopList\"]\n",
    "    return train_stop_list"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f2bd6256f8eca47",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## 输出 : 从赣榆到上海的需要的车次信息\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "687c412889097a01",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-17T11:32:55.113481Z",
     "start_time": "2024-02-17T11:32:54.816114Z"
    },
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[  MainThread ] {\"ResponseStatus\":{\"Timestamp\":\"/Date(1708518248512+0800)/\",\"Ack\":\"Success\",\"Errors\":[],\"Build\":null,\"Version\":null,\"Extension\":[{\"Id\":\"app_cat_id\",\"Version\":null,\"ContentType\":null,\"Value\":\"100025527-0a30441b-474588-1152774\"},{\"Id\":\"CLOGGING_TRACE_ID\",\"Version\":null,\"ContentType\":null,\"Value\":\"5252631049274075051\"},{\"Id\":\"RootMessageId\",\"Version\":null,\"ContentType\":null,\"Value\":\"100025527-0a30441b-474588-1152773\"}]},\"ResponseBody\":{\"ResponseStatus\":null,\"DepartureSearchPinYin\":\"shanghaihongqiao\",\"DepartureSearchPinYinV2\":null,\"DepartureSearchName\":\"赣榆\",\"ArrivalSearchPinYin\":\"ganyu\",\"ArrivalSearchPinYinV2\":null,\"ArrivalSearchName\":\"上海虹桥\",\"DepartureDate\":\"/Date(1708617600000+0800)/\",\"BookingSystemType\":0,\"DepartureCity\":{\"CtripCityID\":21404,\"CityName\":\"赣榆\",\"CityNameEn\":null,\"CityCode\":\"\"},\"ArriveCity\":{\"CtripCityID\":2,\"CityName\":\"上海\",\"CityNameEn\":null,\"CityCode\":\"SHA\"},\"TrainItems\":[{\"TrainID\":0,\"TrainName\":\"D2131\",\"TrainShortName\":\"D\",\"Bookable\":true,\"OnlineDisplay\":false,\"OfflineDisplay\":false,\"TrainTypeID\":0,\"TrainTypeName\":null,\"TrainTypeShortName\":\"D\",\"StartStationID\":0,\"StartStationName\":\"赣榆\",\"EndStationID\":0,\"EndStationName\":\"上海虹桥\",\"StartTime\":\"08:41\",\"EndTime\":\"12:41\",\"TotalDistance\":0,\"TotalTakeDays\":0,\"IsDirect\":false,\"UseTime\":240,\"PreSaleTime\":null,\"IsStartStation\":false,\"IsEndStation\":true,\"PreSaleDay\":14,\"IsSaleStop\":false,\"NoteRemark\":null,\"IsSupportCard\":\"1\",\"TicketResult\":{\"DepartureStationID\":0,\"DepartureStationName\":\"赣榆\",\"ArrivalStationID\":0,\"ArrivalStationName\":\"上海虹桥\",\"DepartureTime\":\"08:41\",\"ArrivalTime\":\"12:41\",\"Distance\":0,\"TakeDays\":0,\"TrainShortName\":null,\"DepartureStationPinyin\":null,\"ArrivalStationPinyin\":null,\"DepartureIsStart\":false,\"ArrivalIsEnd\":false,\"TicketItems\":[{\"TicketID\":0,\"Bookable\":true,\"SeatTypeID\":0,\"SeatTypeName\":\"二等座\",\"Price\":221,\"ShowPrice\":221,\"Inventory\":99},{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"一等座\",\"Price\":352,\"ShowPrice\":352,\"Inventory\":0},{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"无座\",\"Price\":221,\"ShowPrice\":221,\"Inventory\":0}]},\"IsCanHB\":true},{\"TrainID\":0,\"TrainName\":\"D2923\",\"TrainShortName\":\"D\",\"Bookable\":false,\"OnlineDisplay\":false,\"OfflineDisplay\":false,\"TrainTypeID\":0,\"TrainTypeName\":null,\"TrainTypeShortName\":\"D\",\"StartStationID\":0,\"StartStationName\":\"赣榆\",\"EndStationID\":0,\"EndStationName\":\"上海虹桥\",\"StartTime\":\"10:11\",\"EndTime\":\"14:41\",\"TotalDistance\":0,\"TotalTakeDays\":0,\"IsDirect\":false,\"UseTime\":270,\"PreSaleTime\":null,\"IsStartStation\":false,\"IsEndStation\":true,\"PreSaleDay\":14,\"IsSaleStop\":false,\"NoteRemark\":null,\"IsSupportCard\":\"1\",\"TicketResult\":{\"DepartureStationID\":0,\"DepartureStationName\":\"赣榆\",\"ArrivalStationID\":0,\"ArrivalStationName\":\"上海虹桥\",\"DepartureTime\":\"10:11\",\"ArrivalTime\":\"14:41\",\"Distance\":0,\"TakeDays\":0,\"TrainShortName\":null,\"DepartureStationPinyin\":null,\"ArrivalStationPinyin\":null,\"DepartureIsStart\":false,\"ArrivalIsEnd\":false,\"TicketItems\":[{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"二等座\",\"Price\":232,\"ShowPrice\":232,\"Inventory\":0},{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"一等座\",\"Price\":372,\"ShowPrice\":372,\"Inventory\":0},{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"无座\",\"Price\":232,\"ShowPrice\":232,\"Inventory\":0}]},\"IsCanHB\":true},{\"TrainID\":0,\"TrainName\":\"D2135\",\"TrainShortName\":\"D\",\"Bookable\":false,\"OnlineDisplay\":false,\"OfflineDisplay\":false,\"TrainTypeID\":0,\"TrainTypeName\":null,\"TrainTypeShortName\":\"D\",\"StartStationID\":0,\"StartStationName\":\"赣榆\",\"EndStationID\":0,\"EndStationName\":\"上海虹桥\",\"StartTime\":\"10:49\",\"EndTime\":\"15:10\",\"TotalDistance\":0,\"TotalTakeDays\":0,\"IsDirect\":false,\"UseTime\":261,\"PreSaleTime\":null,\"IsStartStation\":false,\"IsEndStation\":true,\"PreSaleDay\":14,\"IsSaleStop\":false,\"NoteRemark\":null,\"IsSupportCard\":\"1\",\"TicketResult\":{\"DepartureStationID\":0,\"DepartureStationName\":\"赣榆\",\"ArrivalStationID\":0,\"ArrivalStationName\":\"上海虹桥\",\"DepartureTime\":\"10:49\",\"ArrivalTime\":\"15:10\",\"Distance\":0,\"TakeDays\":0,\"TrainShortName\":null,\"DepartureStationPinyin\":null,\"ArrivalStationPinyin\":null,\"DepartureIsStart\":false,\"ArrivalIsEnd\":false,\"TicketItems\":[{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"二等座\",\"Price\":220,\"ShowPrice\":220,\"Inventory\":0},{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"一等座\",\"Price\":352,\"ShowPrice\":352,\"Inventory\":0},{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"无座\",\"Price\":220,\"ShowPrice\":220,\"Inventory\":0}]},\"IsCanHB\":true},{\"TrainID\":0,\"TrainName\":\"G7585\",\"TrainShortName\":\"G\",\"Bookable\":false,\"OnlineDisplay\":false,\"OfflineDisplay\":false,\"TrainTypeID\":0,\"TrainTypeName\":null,\"TrainTypeShortName\":\"G\",\"StartStationID\":0,\"StartStationName\":\"赣榆\",\"EndStationID\":0,\"EndStationName\":\"上海虹桥\",\"StartTime\":\"13:03\",\"EndTime\":\"17:12\",\"TotalDistance\":0,\"TotalTakeDays\":0,\"IsDirect\":false,\"UseTime\":249,\"PreSaleTime\":null,\"IsStartStation\":true,\"IsEndStation\":false,\"PreSaleDay\":14,\"IsSaleStop\":false,\"NoteRemark\":null,\"IsSupportCard\":\"1\",\"TicketResult\":{\"DepartureStationID\":0,\"DepartureStationName\":\"赣榆\",\"ArrivalStationID\":0,\"ArrivalStationName\":\"上海虹桥\",\"DepartureTime\":\"13:03\",\"ArrivalTime\":\"17:12\",\"Distance\":0,\"TakeDays\":0,\"TrainShortName\":null,\"DepartureStationPinyin\":null,\"ArrivalStationPinyin\":null,\"DepartureIsStart\":false,\"ArrivalIsEnd\":false,\"TicketItems\":[{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"二等座\",\"Price\":290,\"ShowPrice\":290,\"Inventory\":0},{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"一等座\",\"Price\":463,\"ShowPrice\":463,\"Inventory\":0},{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"无座\",\"Price\":290,\"ShowPrice\":290,\"Inventory\":0}]},\"IsCanHB\":true},{\"TrainID\":0,\"TrainName\":\"D2145\",\"TrainShortName\":\"D\",\"Bookable\":false,\"OnlineDisplay\":false,\"OfflineDisplay\":false,\"TrainTypeID\":0,\"TrainTypeName\":null,\"TrainTypeShortName\":\"D\",\"StartStationID\":0,\"StartStationName\":\"赣榆\",\"EndStationID\":0,\"EndStationName\":\"上海虹桥\",\"StartTime\":\"15:50\",\"EndTime\":\"19:09\",\"TotalDistance\":0,\"TotalTakeDays\":0,\"IsDirect\":false,\"UseTime\":199,\"PreSaleTime\":null,\"IsStartStation\":false,\"IsEndStation\":true,\"PreSaleDay\":14,\"IsSaleStop\":false,\"NoteRemark\":null,\"IsSupportCard\":\"1\",\"TicketResult\":{\"DepartureStationID\":0,\"DepartureStationName\":\"赣榆\",\"ArrivalStationID\":0,\"ArrivalStationName\":\"上海虹桥\",\"DepartureTime\":\"15:50\",\"ArrivalTime\":\"19:09\",\"Distance\":0,\"TakeDays\":0,\"TrainShortName\":null,\"DepartureStationPinyin\":null,\"ArrivalStationPinyin\":null,\"DepartureIsStart\":false,\"ArrivalIsEnd\":false,\"TicketItems\":[{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"二等座\",\"Price\":233,\"ShowPrice\":233,\"Inventory\":0},{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"一等座\",\"Price\":371,\"ShowPrice\":371,\"Inventory\":0},{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"无座\",\"Price\":233,\"ShowPrice\":233,\"Inventory\":0}]},\"IsCanHB\":true},{\"TrainID\":0,\"TrainName\":\"D2927\",\"TrainShortName\":\"D\",\"Bookable\":false,\"OnlineDisplay\":false,\"OfflineDisplay\":false,\"TrainTypeID\":0,\"TrainTypeName\":null,\"TrainTypeShortName\":\"D\",\"StartStationID\":0,\"StartStationName\":\"赣榆\",\"EndStationID\":0,\"EndStationName\":\"上海虹桥\",\"StartTime\":\"18:22\",\"EndTime\":\"22:38\",\"TotalDistance\":0,\"TotalTakeDays\":0,\"IsDirect\":false,\"UseTime\":256,\"PreSaleTime\":null,\"IsStartStation\":false,\"IsEndStation\":true,\"PreSaleDay\":14,\"IsSaleStop\":false,\"NoteRemark\":null,\"IsSupportCard\":\"1\",\"TicketResult\":{\"DepartureStationID\":0,\"DepartureStationName\":\"赣榆\",\"ArrivalStationID\":0,\"ArrivalStationName\":\"上海虹桥\",\"DepartureTime\":\"18:22\",\"ArrivalTime\":\"22:38\",\"Distance\":0,\"TakeDays\":0,\"TrainShortName\":null,\"DepartureStationPinyin\":null,\"ArrivalStationPinyin\":null,\"DepartureIsStart\":false,\"ArrivalIsEnd\":false,\"TicketItems\":[{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"二等座\",\"Price\":250,\"ShowPrice\":250,\"Inventory\":0},{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"一等座\",\"Price\":399,\"ShowPrice\":399,\"Inventory\":0},{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"无座\",\"Price\":250,\"ShowPrice\":250,\"Inventory\":0}]},\"IsCanHB\":true},{\"TrainID\":0,\"TrainName\":\"D2151\",\"TrainShortName\":\"D\",\"Bookable\":false,\"OnlineDisplay\":false,\"OfflineDisplay\":false,\"TrainTypeID\":0,\"TrainTypeName\":null,\"TrainTypeShortName\":\"D\",\"StartStationID\":0,\"StartStationName\":\"赣榆\",\"EndStationID\":0,\"EndStationName\":\"上海虹桥\",\"StartTime\":\"18:34\",\"EndTime\":\"22:32\",\"TotalDistance\":0,\"TotalTakeDays\":0,\"IsDirect\":false,\"UseTime\":238,\"PreSaleTime\":null,\"IsStartStation\":false,\"IsEndStation\":true,\"PreSaleDay\":14,\"IsSaleStop\":false,\"NoteRemark\":null,\"IsSupportCard\":\"1\",\"TicketResult\":{\"DepartureStationID\":0,\"DepartureStationName\":\"赣榆\",\"ArrivalStationID\":0,\"ArrivalStationName\":\"上海虹桥\",\"DepartureTime\":\"18:34\",\"ArrivalTime\":\"22:32\",\"Distance\":0,\"TakeDays\":0,\"TrainShortName\":null,\"DepartureStationPinyin\":null,\"ArrivalStationPinyin\":null,\"DepartureIsStart\":false,\"ArrivalIsEnd\":false,\"TicketItems\":[{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"二等座\",\"Price\":233,\"ShowPrice\":233,\"Inventory\":0},{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"一等座\",\"Price\":371,\"ShowPrice\":371,\"Inventory\":0},{\"TicketID\":0,\"Bookable\":false,\"SeatTypeID\":0,\"SeatTypeName\":\"无座\",\"Price\":233,\"ShowPrice\":233,\"Inventory\":0}]},\"IsCanHB\":true}]}}\n"
     ]
    }
   ],
   "source": [
    "response = httpx.post(\n",
    "    \"https://m.suanya.com/restapi/soa2/14666/json/GetBookingByStationV3ForPC\",\n",
    "    headers={\n",
    "        \"authority\": \"m.suanya.com\",\n",
    "        \"accept\": \"*/*\",\n",
    "        \"accept-language\": \"zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6\",\n",
    "        \"cache-control\": \"max-age=0\",\n",
    "        \"content-type\": \"application/x-www-form-urlencoded; charset=UTF-8\",\n",
    "        \"if-modified-since\": \"Thu, 01 Jan 1970 00:00:00 GMT\",\n",
    "        \"origin\": \"https://www.suanya.com\",\n",
    "        \"referer\": \"https://www.suanya.com/\",\n",
    "        \"sec-ch-ua\": '\"Not A(Brand\";v=\"99\", \"Microsoft Edge\";v=\"121\", \"Chromium\";v=\"121\"',\n",
    "        \"sec-ch-ua-mobile\": \"?0\",\n",
    "        \"sec-ch-ua-platform\": '\"Windows\"',\n",
    "        \"sec-fetch-dest\": \"empty\",\n",
    "        \"sec-fetch-mode\": \"cors\",\n",
    "        \"sec-fetch-site\": \"same-site\",\n",
    "    },\n",
    "    data={\n",
    "        \"ArriveStation\": station_end,\n",
    "        \"ChannelName\": \"ctrip.pc\",\n",
    "        \"DepartDate\": date,\n",
    "        \"DepartStation\": station_start,\n",
    "    },\n",
    ")\n",
    "print(response.text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "9f7ac9937572c3d8",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-17T11:37:12.757554Z",
     "start_time": "2024-02-17T11:37:12.746385Z"
    },
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>起点站</th>\n",
       "      <th>终点站</th>\n",
       "      <th>车次</th>\n",
       "      <th>开始时间</th>\n",
       "      <th>结束时间</th>\n",
       "      <th>耗时</th>\n",
       "      <th>一等座价格</th>\n",
       "      <th>一等座余票量</th>\n",
       "      <th>二等座价格</th>\n",
       "      <th>二等座余票量</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>赣榆</td>\n",
       "      <td>上海虹桥</td>\n",
       "      <td>D2145</td>\n",
       "      <td>15:50</td>\n",
       "      <td>19:09</td>\n",
       "      <td>3小时19分钟</td>\n",
       "      <td>371</td>\n",
       "      <td>0</td>\n",
       "      <td>233</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  起点站   终点站     车次   开始时间   结束时间       耗时  一等座价格  一等座余票量  二等座价格  二等座余票量\n",
       "0  赣榆  上海虹桥  D2145  15:50  19:09  3小时19分钟    371       0    233       0"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用orgjson格式化输出\n",
    "text = response.text\n",
    "data = orjson.loads(text)\n",
    "TrainItems_all = data[\"ResponseBody\"][\"TrainItems\"]\n",
    "\n",
    "# filter_train_names\n",
    "TrainItems = [\n",
    "    item for item in TrainItems_all if item[\"TrainName\"] in filter_train_names\n",
    "]\n",
    "\n",
    "train_items_df = transform_booking_train_items_info_to_dataframe(TrainItems)\n",
    "train_items_df.insert(0, \"起点站\", station_start)\n",
    "train_items_df.insert(1, \"终点站\", station_end)\n",
    "train_items_df"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7b7ee48cba784d89",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "# 使用车次一个进行流程测试, 查询从赣榆到上海的 d2131 的车次的所有的停靠站信息\n",
    "\n",
    "`输出` : item_stop_list_stations\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "d12bb42cffc0e5a9",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-17T11:32:55.326197Z",
     "start_time": "2024-02-17T11:32:55.118018Z"
    },
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>车次</th>\n",
       "      <th>StationSequence</th>\n",
       "      <th>StationName</th>\n",
       "      <th>DepartureTime</th>\n",
       "      <th>ArrivalTime</th>\n",
       "      <th>StopTimes</th>\n",
       "      <th>DistanceFromStart</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>D2145</td>\n",
       "      <td>1</td>\n",
       "      <td>青岛北</td>\n",
       "      <td>14:05</td>\n",
       "      <td>14:05</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>D2145</td>\n",
       "      <td>2</td>\n",
       "      <td>日照西</td>\n",
       "      <td>15:10</td>\n",
       "      <td>15:05</td>\n",
       "      <td>5</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>D2145</td>\n",
       "      <td>3</td>\n",
       "      <td>岚山西</td>\n",
       "      <td>15:29</td>\n",
       "      <td>15:23</td>\n",
       "      <td>6</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>D2145</td>\n",
       "      <td>4</td>\n",
       "      <td>赣榆</td>\n",
       "      <td>15:50</td>\n",
       "      <td>15:48</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>D2145</td>\n",
       "      <td>5</td>\n",
       "      <td>连云港</td>\n",
       "      <td>16:12</td>\n",
       "      <td>16:07</td>\n",
       "      <td>5</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>D2145</td>\n",
       "      <td>6</td>\n",
       "      <td>盐城</td>\n",
       "      <td>17:23</td>\n",
       "      <td>17:19</td>\n",
       "      <td>4</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>D2145</td>\n",
       "      <td>7</td>\n",
       "      <td>上海虹桥</td>\n",
       "      <td>19:09</td>\n",
       "      <td>19:09</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      车次  StationSequence StationName DepartureTime ArrivalTime  StopTimes  \\\n",
       "0  D2145                1         青岛北         14:05       14:05          0   \n",
       "1  D2145                2         日照西         15:10       15:05          5   \n",
       "2  D2145                3         岚山西         15:29       15:23          6   \n",
       "3  D2145                4          赣榆         15:50       15:48          2   \n",
       "4  D2145                5         连云港         16:12       16:07          5   \n",
       "5  D2145                6          盐城         17:23       17:19          4   \n",
       "6  D2145                7        上海虹桥         19:09       19:09          0   \n",
       "\n",
       "   DistanceFromStart  \n",
       "0                  0  \n",
       "1                  0  \n",
       "2                  0  \n",
       "3                  0  \n",
       "4                  0  \n",
       "5                  0  \n",
       "6                  0  "
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_item = TrainItems[0]\n",
    "station_start = train_item[\"StartStationName\"]\n",
    "station_end = train_item[\"EndStationName\"]\n",
    "# 获取二等座价格\n",
    "train_item_second_price = next(\n",
    "    (\n",
    "        ticket[\"Price\"]\n",
    "        for ticket in train_item[\"TicketResult\"][\"TicketItems\"]\n",
    "        if ticket[\"SeatTypeName\"] == \"二等座\"\n",
    "    ),\n",
    "    None,\n",
    ")\n",
    "transform_booking_train_items_info_to_dataframe([train_item])\n",
    "\n",
    "item_stop_list_stations = query_stop_station_list(\n",
    "    train_item[\"TrainName\"], date, station_start, station_end\n",
    ")\n",
    "\n",
    "item_stop_list_station_df = pd.DataFrame(item_stop_list_stations)\n",
    "item_stop_list_station_df.insert(0, \"车次\", train_item[\"TrainName\"])\n",
    "item_stop_list_station_df"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3affd5dda4aeeea0",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "# stationName 和始发站的映射关系的映射关系\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "26767323efed25ff",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-17T11:32:55.333805Z",
     "start_time": "2024-02-17T11:32:55.328032Z"
    },
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>车次</th>\n",
       "      <th>站名</th>\n",
       "      <th>出发时间</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>D2145</td>\n",
       "      <td>青岛北</td>\n",
       "      <td>14:05</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>D2145</td>\n",
       "      <td>日照西</td>\n",
       "      <td>15:10</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>D2145</td>\n",
       "      <td>岚山西</td>\n",
       "      <td>15:29</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>D2145</td>\n",
       "      <td>赣榆</td>\n",
       "      <td>15:50</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>D2145</td>\n",
       "      <td>连云港</td>\n",
       "      <td>16:12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>D2145</td>\n",
       "      <td>盐城</td>\n",
       "      <td>17:23</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>D2145</td>\n",
       "      <td>上海虹桥</td>\n",
       "      <td>19:09</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      车次    站名   出发时间\n",
       "0  D2145   青岛北  14:05\n",
       "1  D2145   日照西  15:10\n",
       "2  D2145   岚山西  15:29\n",
       "3  D2145    赣榆  15:50\n",
       "4  D2145   连云港  16:12\n",
       "5  D2145    盐城  17:23\n",
       "6  D2145  上海虹桥  19:09"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# stationName和始发站的映射关系的映射关系\n",
    "item_stop_list_station_name_departure_dict = {\n",
    "    item[\"StationName\"]: item[\"DepartureTime\"] for item in item_stop_list_stations\n",
    "}\n",
    "\n",
    "item_stop_list_station_name_departure_dict_df = pd.DataFrame(\n",
    "    item_stop_list_station_name_departure_dict.items(), columns=[\"站名\", \"出发时间\"]\n",
    ")\n",
    "# 增加车次列在开头\n",
    "item_stop_list_station_name_departure_dict_df.insert(0, \"车次\", train_item[\"TrainName\"])\n",
    "item_stop_list_station_name_departure_dict_df"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9342a358263dfebb",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "> 由于一辆车次在不同的起点, 车次的名称不一样. 需要确定停靠站的每一列的车次名称.\n",
    "> 分成三块 起点 : 上车站点 : 终点站 . 需要从[起始点, 上车站点] 和 (上车站点, 终点站] 两个列表中找出车次名称做叉乘, 得到所有的车次名称\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "94f74fda6dbbfe2a",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-17T11:32:55.336094Z",
     "start_time": "2024-02-17T11:32:55.332415Z"
    },
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>站名</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>青岛北</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>日照西</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>岚山西</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>赣榆</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>连云港</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>盐城</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>上海虹桥</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     站名\n",
       "0   青岛北\n",
       "1   日照西\n",
       "2   岚山西\n",
       "3    赣榆\n",
       "4   连云港\n",
       "5    盐城\n",
       "6  上海虹桥"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# [起始点, 上车站点] 和 (上车站点, 终点站] 两个列表中找出车次名称做叉乘, 得到所有的车次名称\n",
    "item_stop_station_names = [item[\"StationName\"] for item in item_stop_list_stations]\n",
    "# item_stop_station_names转成df\n",
    "pd.DataFrame(item_stop_station_names, columns=[\"站名\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6b1725084656c824",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "从[起始点, 上车站点] 和 (上车站点, 终点站] 两个列表中找出车次名称做叉乘, 得到所有的车次名称\n",
    "`输出` : xlist\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "d2052af4f3678a90",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-17T11:32:55.344235Z",
     "start_time": "2024-02-17T11:32:55.337867Z"
    },
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[  MainThread ] 0 3 6\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>原始车次</th>\n",
       "      <th>起点</th>\n",
       "      <th>终点</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>D2145</td>\n",
       "      <td>赣榆</td>\n",
       "      <td>上海虹桥</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>D2145</td>\n",
       "      <td>赣榆</td>\n",
       "      <td>盐城</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>D2145</td>\n",
       "      <td>赣榆</td>\n",
       "      <td>连云港</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>D2145</td>\n",
       "      <td>岚山西</td>\n",
       "      <td>上海虹桥</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>D2145</td>\n",
       "      <td>岚山西</td>\n",
       "      <td>盐城</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>D2145</td>\n",
       "      <td>岚山西</td>\n",
       "      <td>连云港</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>D2145</td>\n",
       "      <td>日照西</td>\n",
       "      <td>上海虹桥</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>D2145</td>\n",
       "      <td>日照西</td>\n",
       "      <td>盐城</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>D2145</td>\n",
       "      <td>日照西</td>\n",
       "      <td>连云港</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>D2145</td>\n",
       "      <td>青岛北</td>\n",
       "      <td>上海虹桥</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>D2145</td>\n",
       "      <td>青岛北</td>\n",
       "      <td>盐城</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>D2145</td>\n",
       "      <td>青岛北</td>\n",
       "      <td>连云港</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     原始车次   起点    终点\n",
       "0   D2145   赣榆  上海虹桥\n",
       "1   D2145   赣榆    盐城\n",
       "2   D2145   赣榆   连云港\n",
       "3   D2145  岚山西  上海虹桥\n",
       "4   D2145  岚山西    盐城\n",
       "5   D2145  岚山西   连云港\n",
       "6   D2145  日照西  上海虹桥\n",
       "7   D2145  日照西    盐城\n",
       "8   D2145  日照西   连云港\n",
       "9   D2145  青岛北  上海虹桥\n",
       "10  D2145  青岛北    盐城\n",
       "11  D2145  青岛北   连云港"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 按照起点名和终点名分成两个列表, 进行叉乘, 使用包含, 而不是index, 因为名字可能不一样,但是一定包含\n",
    "start_station_index = 0  # 和middle_station_index可能相同\n",
    "middle_station_index = 0  # 和end_station_index一定不同\n",
    "end_station_index = 0\n",
    "for index, station_name in enumerate(item_stop_station_names):\n",
    "    if station_start in station_name:\n",
    "        middle_station_index = index\n",
    "    if station_end in station_name:\n",
    "        end_station_index = index\n",
    "# 两个队列的叉乘\n",
    "print(start_station_index, middle_station_index, end_station_index)\n",
    "xlist = []\n",
    "\n",
    "index_generator = (i for i in range(0, 10000000))\n",
    "for i in range(middle_station_index, start_station_index - 1, -1):\n",
    "    for j in range(len(item_stop_station_names) - 1, middle_station_index, -1):\n",
    "        xlist.append([item_stop_station_names[i], item_stop_station_names[j]])\n",
    "\n",
    "xlist_df = pd.DataFrame(xlist, columns=[\"起点\", \"终点\"])\n",
    "xlist_df.insert(0, \"原始车次\", train_item[\"TrainName\"])\n",
    "xlist_df"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e1572fa4ef08b71",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "> xlist 中的站点的车次关系,查询余票信息. 由于是按照车站名称查询, 两个车站之间有很多车次, 使用发车时间进行过滤,找到原始的车次\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "c4d55291b900f9b1",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-17T11:32:55.857054Z",
     "start_time": "2024-02-17T11:32:55.341381Z"
    },
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[  MainThread ] 开始查询车次信息, 总查询次数: 12\n",
      "[  MainThread ] 开始查询 0\n",
      "[  MainThread ] 查询结束,cost= 1251 ms,  查询数量12,\n",
      " [0, 5, 2, 3, 6, 9, 7, 4, 1, 8, 10, 11]\n"
     ]
    }
   ],
   "source": [
    "#\n",
    "import time\n",
    "import vthread\n",
    "\n",
    "xlist_item_results = []\n",
    "finished_index = []\n",
    "# 打印一下进度条\n",
    "print(\"开始查询车次信息, 总查询次数:\", len(xlist))\n",
    "print(\"开始查询\", len(xlist_item_results))\n",
    "\n",
    "# 多线程查询\n",
    "T1 = time.time()\n",
    "\n",
    "\n",
    "@vthread.pool(10)\n",
    "def xlist_item_job(index, xlist_item_start_station, xlist_item_end_station):\n",
    "    xlist_item_train_items = query_booking_by_station_v3_for_pc(\n",
    "        xlist_item_start_station, xlist_item_end_station, date\n",
    "    )\n",
    "    # 过滤出发车时间是之前dict中的时间的车次\n",
    "    xlist_item_start_station_departure_time = (\n",
    "        item_stop_list_station_name_departure_dict[xlist_item_start_station]\n",
    "    )\n",
    "    xlist_item_train_items = [\n",
    "        item\n",
    "        for item in xlist_item_train_items\n",
    "        if str(item[\"StartTime\"]) == str(xlist_item_start_station_departure_time)\n",
    "    ]\n",
    "\n",
    "    xlist_item_train_items_df = transform_booking_train_items_info_to_dataframe(\n",
    "        xlist_item_train_items\n",
    "    )\n",
    "    # 给df增加一列, 起点站和终点站,放到开头\n",
    "    xlist_item_train_items_df.insert(0, \"起点站\", xlist_item_start_station)\n",
    "    xlist_item_train_items_df.insert(1, \"终点站\", xlist_item_end_station)\n",
    "    xlist_item_results.append(xlist_item_train_items_df)\n",
    "    finished_index.append(index)\n",
    "\n",
    "\n",
    "for index, xlist_item in enumerate(xlist):\n",
    "    xlist_item_start_station = xlist_item[0]\n",
    "    xlist_item_end_station = xlist_item[1]\n",
    "    xlist_item_job(index, xlist_item_start_station, xlist_item_end_station)\n",
    "vthread.pool.wait()\n",
    "T2 = time.time()\n",
    "\n",
    "print(\n",
    "    f\"查询结束,cost= {int((T2 - T1)*1000)} ms,  查询数量{len(xlist_item_results)},\\n {finished_index}\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "63c5fefab54eb56a",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-17T11:32:55.865620Z",
     "start_time": "2024-02-17T11:32:55.858261Z"
    },
    "collapsed": false
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "95daa1539eb706fb",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-17T11:32:55.874194Z",
     "start_time": "2024-02-17T11:32:55.868686Z"
    },
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>原始车次</th>\n",
       "      <th>起点站</th>\n",
       "      <th>终点站</th>\n",
       "      <th>车次</th>\n",
       "      <th>开始时间</th>\n",
       "      <th>结束时间</th>\n",
       "      <th>耗时</th>\n",
       "      <th>一等座价格</th>\n",
       "      <th>一等座余票量</th>\n",
       "      <th>二等座价格</th>\n",
       "      <th>二等座余票量</th>\n",
       "      <th>车次链接</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>D2145</td>\n",
       "      <td>赣榆</td>\n",
       "      <td>上海虹桥</td>\n",
       "      <td>D2145</td>\n",
       "      <td>15:50</td>\n",
       "      <td>19:09</td>\n",
       "      <td>3小时19分钟</td>\n",
       "      <td>371</td>\n",
       "      <td>0</td>\n",
       "      <td>233</td>\n",
       "      <td>0</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=赣榆&amp;toCn=上海虹桥&amp;fromDate=2024-02-23#:~:text=D2145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>D2145</td>\n",
       "      <td>岚山西</td>\n",
       "      <td>上海虹桥</td>\n",
       "      <td>D2145</td>\n",
       "      <td>15:29</td>\n",
       "      <td>19:09</td>\n",
       "      <td>3小时40分钟</td>\n",
       "      <td>394</td>\n",
       "      <td>0</td>\n",
       "      <td>247</td>\n",
       "      <td>0</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=岚山西&amp;toCn=上海虹桥&amp;fromDate=2024-02-23#:~:text=D2145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>D2145</td>\n",
       "      <td>日照西</td>\n",
       "      <td>上海虹桥</td>\n",
       "      <td>D2145</td>\n",
       "      <td>15:10</td>\n",
       "      <td>19:09</td>\n",
       "      <td>3小时59分钟</td>\n",
       "      <td>410</td>\n",
       "      <td>0</td>\n",
       "      <td>257</td>\n",
       "      <td>0</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=日照西&amp;toCn=上海虹桥&amp;fromDate=2024-02-23#:~:text=D2145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>D2145</td>\n",
       "      <td>青岛北</td>\n",
       "      <td>上海虹桥</td>\n",
       "      <td>D2145</td>\n",
       "      <td>14:05</td>\n",
       "      <td>19:09</td>\n",
       "      <td>5小时4分钟</td>\n",
       "      <td>500</td>\n",
       "      <td>0</td>\n",
       "      <td>314</td>\n",
       "      <td>99</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=青岛北&amp;toCn=上海虹桥&amp;fromDate=2024-02-23#:~:text=D2145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>D2145</td>\n",
       "      <td>赣榆</td>\n",
       "      <td>盐城</td>\n",
       "      <td>D2145</td>\n",
       "      <td>15:50</td>\n",
       "      <td>17:19</td>\n",
       "      <td>1小时29分钟</td>\n",
       "      <td>134</td>\n",
       "      <td>0</td>\n",
       "      <td>84</td>\n",
       "      <td>0</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=赣榆&amp;toCn=盐城&amp;fromDate=2024-02-23#:~:text=D2145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>D2145</td>\n",
       "      <td>岚山西</td>\n",
       "      <td>盐城</td>\n",
       "      <td>D2145</td>\n",
       "      <td>15:29</td>\n",
       "      <td>17:19</td>\n",
       "      <td>1小时50分钟</td>\n",
       "      <td>157</td>\n",
       "      <td>0</td>\n",
       "      <td>98</td>\n",
       "      <td>0</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=岚山西&amp;toCn=盐城&amp;fromDate=2024-02-23#:~:text=D2145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>D2145</td>\n",
       "      <td>日照西</td>\n",
       "      <td>盐城</td>\n",
       "      <td>D2145</td>\n",
       "      <td>15:10</td>\n",
       "      <td>17:19</td>\n",
       "      <td>2小时9分钟</td>\n",
       "      <td>173</td>\n",
       "      <td>0</td>\n",
       "      <td>108</td>\n",
       "      <td>0</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=日照西&amp;toCn=盐城&amp;fromDate=2024-02-23#:~:text=D2145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>D2145</td>\n",
       "      <td>青岛北</td>\n",
       "      <td>盐城</td>\n",
       "      <td>D2145</td>\n",
       "      <td>14:05</td>\n",
       "      <td>17:19</td>\n",
       "      <td>3小时14分钟</td>\n",
       "      <td>263</td>\n",
       "      <td>0</td>\n",
       "      <td>165</td>\n",
       "      <td>1</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=青岛北&amp;toCn=盐城&amp;fromDate=2024-02-23#:~:text=D2145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>D2145</td>\n",
       "      <td>赣榆</td>\n",
       "      <td>连云港</td>\n",
       "      <td>D2145</td>\n",
       "      <td>15:50</td>\n",
       "      <td>16:07</td>\n",
       "      <td>0小时17分钟</td>\n",
       "      <td>21</td>\n",
       "      <td>0</td>\n",
       "      <td>13</td>\n",
       "      <td>0</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=赣榆&amp;toCn=连云港&amp;fromDate=2024-02-23#:~:text=D2145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>D2145</td>\n",
       "      <td>岚山西</td>\n",
       "      <td>连云港</td>\n",
       "      <td>D2145</td>\n",
       "      <td>15:29</td>\n",
       "      <td>16:07</td>\n",
       "      <td>0小时38分钟</td>\n",
       "      <td>43</td>\n",
       "      <td>0</td>\n",
       "      <td>27</td>\n",
       "      <td>0</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=岚山西&amp;toCn=连云港&amp;fromDate=2024-02-23#:~:text=D2145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>D2145</td>\n",
       "      <td>日照西</td>\n",
       "      <td>连云港</td>\n",
       "      <td>D2145</td>\n",
       "      <td>15:10</td>\n",
       "      <td>16:07</td>\n",
       "      <td>0小时57分钟</td>\n",
       "      <td>59</td>\n",
       "      <td>0</td>\n",
       "      <td>37</td>\n",
       "      <td>0</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=日照西&amp;toCn=连云港&amp;fromDate=2024-02-23#:~:text=D2145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>D2145</td>\n",
       "      <td>青岛北</td>\n",
       "      <td>连云港</td>\n",
       "      <td>D3187</td>\n",
       "      <td>14:05</td>\n",
       "      <td>15:23</td>\n",
       "      <td>1小时18分钟</td>\n",
       "      <td>106</td>\n",
       "      <td>0</td>\n",
       "      <td>66</td>\n",
       "      <td>0</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=青岛北&amp;toCn=连云港&amp;fromDate=2024-02-23#:~:text=D3187</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>D2145</td>\n",
       "      <td>青岛北</td>\n",
       "      <td>连云港</td>\n",
       "      <td>D2145</td>\n",
       "      <td>14:05</td>\n",
       "      <td>16:07</td>\n",
       "      <td>2小时2分钟</td>\n",
       "      <td>150</td>\n",
       "      <td>0</td>\n",
       "      <td>94</td>\n",
       "      <td>2</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=青岛北&amp;toCn=连云港&amp;fromDate=2024-02-23#:~:text=D2145</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     原始车次  起点站   终点站     车次   开始时间   结束时间       耗时  一等座价格  一等座余票量  二等座价格  \\\n",
       "0   D2145   赣榆  上海虹桥  D2145  15:50  19:09  3小时19分钟    371       0    233   \n",
       "1   D2145  岚山西  上海虹桥  D2145  15:29  19:09  3小时40分钟    394       0    247   \n",
       "2   D2145  日照西  上海虹桥  D2145  15:10  19:09  3小时59分钟    410       0    257   \n",
       "3   D2145  青岛北  上海虹桥  D2145  14:05  19:09   5小时4分钟    500       0    314   \n",
       "4   D2145   赣榆    盐城  D2145  15:50  17:19  1小时29分钟    134       0     84   \n",
       "5   D2145  岚山西    盐城  D2145  15:29  17:19  1小时50分钟    157       0     98   \n",
       "6   D2145  日照西    盐城  D2145  15:10  17:19   2小时9分钟    173       0    108   \n",
       "7   D2145  青岛北    盐城  D2145  14:05  17:19  3小时14分钟    263       0    165   \n",
       "8   D2145   赣榆   连云港  D2145  15:50  16:07  0小时17分钟     21       0     13   \n",
       "9   D2145  岚山西   连云港  D2145  15:29  16:07  0小时38分钟     43       0     27   \n",
       "10  D2145  日照西   连云港  D2145  15:10  16:07  0小时57分钟     59       0     37   \n",
       "11  D2145  青岛北   连云港  D3187  14:05  15:23  1小时18分钟    106       0     66   \n",
       "12  D2145  青岛北   连云港  D2145  14:05  16:07   2小时2分钟    150       0     94   \n",
       "\n",
       "    二等座余票量  \\\n",
       "0        0   \n",
       "1        0   \n",
       "2        0   \n",
       "3       99   \n",
       "4        0   \n",
       "5        0   \n",
       "6        0   \n",
       "7        1   \n",
       "8        0   \n",
       "9        0   \n",
       "10       0   \n",
       "11       0   \n",
       "12       2   \n",
       "\n",
       "                                                                                             车次链接  \n",
       "0    https://www.suanya.com/pages/trainList?fromCn=赣榆&toCn=上海虹桥&fromDate=2024-02-23#:~:text=D2145  \n",
       "1   https://www.suanya.com/pages/trainList?fromCn=岚山西&toCn=上海虹桥&fromDate=2024-02-23#:~:text=D2145  \n",
       "2   https://www.suanya.com/pages/trainList?fromCn=日照西&toCn=上海虹桥&fromDate=2024-02-23#:~:text=D2145  \n",
       "3   https://www.suanya.com/pages/trainList?fromCn=青岛北&toCn=上海虹桥&fromDate=2024-02-23#:~:text=D2145  \n",
       "4      https://www.suanya.com/pages/trainList?fromCn=赣榆&toCn=盐城&fromDate=2024-02-23#:~:text=D2145  \n",
       "5     https://www.suanya.com/pages/trainList?fromCn=岚山西&toCn=盐城&fromDate=2024-02-23#:~:text=D2145  \n",
       "6     https://www.suanya.com/pages/trainList?fromCn=日照西&toCn=盐城&fromDate=2024-02-23#:~:text=D2145  \n",
       "7     https://www.suanya.com/pages/trainList?fromCn=青岛北&toCn=盐城&fromDate=2024-02-23#:~:text=D2145  \n",
       "8     https://www.suanya.com/pages/trainList?fromCn=赣榆&toCn=连云港&fromDate=2024-02-23#:~:text=D2145  \n",
       "9    https://www.suanya.com/pages/trainList?fromCn=岚山西&toCn=连云港&fromDate=2024-02-23#:~:text=D2145  \n",
       "10   https://www.suanya.com/pages/trainList?fromCn=日照西&toCn=连云港&fromDate=2024-02-23#:~:text=D2145  \n",
       "11   https://www.suanya.com/pages/trainList?fromCn=青岛北&toCn=连云港&fromDate=2024-02-23#:~:text=D3187  \n",
       "12   https://www.suanya.com/pages/trainList?fromCn=青岛北&toCn=连云港&fromDate=2024-02-23#:~:text=D2145  "
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将xlist_item_results合并成一个df, 并且生成index\n",
    "xlist_item_results_df = pd.concat(xlist_item_results, ignore_index=True)\n",
    "# 增加原始车次列\n",
    "xlist_item_results_df.insert(0, \"原始车次\", train_item[\"TrainName\"])\n",
    "# item_stop_station_names中有站名, 按照xlist_item_results_df中的终点站和起点站进行排序, 先按照站名在item_stop_station_names中越靠后则优先级越高. 终点站比较特殊,按照靠近配置中的终点站的距离排序.\n",
    "xlist_item_results_df[\"起点站优先级\"] = xlist_item_results_df[\"起点站\"].apply(\n",
    "    lambda x: item_stop_station_names.index(x)\n",
    ")\n",
    "xlist_item_results_df[\"终点站优先级\"] = xlist_item_results_df[\"终点站\"].apply(\n",
    "    lambda x: abs(\n",
    "        item_stop_station_names.index(x) - item_stop_station_names.index(station_end)\n",
    "    )\n",
    ")\n",
    "# 一等座价格排序优先级,\n",
    "xlist_item_results_df[\"一等座价格优先级\"] = xlist_item_results_df[\"一等座价格\"].apply(\n",
    "    lambda x: 0 if x is None else x\n",
    ")\n",
    "xlist_item_results_df = xlist_item_results_df.sort_values(\n",
    "    by=[\"终点站优先级\", \"一等座价格优先级\", \"起点站优先级\"],\n",
    "    ascending=[True, True, False],\n",
    ")\n",
    "# 移除两个优先级列\n",
    "xlist_item_results_df = xlist_item_results_df.drop(\n",
    "    columns=[\"起点站优先级\", \"终点站优先级\", \"一等座价格优先级\"]\n",
    ")\n",
    "# 增加一列, 拼接个http链接    https://www.suanya.com/pages/trainList?fromCn=日照西&toCn=苏州&fromDate=2024-02-19#:~:text=D2923\n",
    "xlist_item_results_df[\"车次链接\"] = xlist_item_results_df.apply(\n",
    "    lambda x: f'https://www.suanya.com/pages/trainList?fromCn={x[\"起点站\"]}&toCn={x[\"终点站\"]}&fromDate={date}#:~:text={x[\"车次\"]}',\n",
    "    axis=1,\n",
    ")\n",
    "xlist_item_results_df = xlist_item_results_df.reset_index(drop=True)\n",
    "xlist_item_results_df"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "edad731c2b37e080",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "# 最终结果 : 保留一等座余量或者二等座余量大于 0 的车次\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "60140ee829a23718",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-17T11:32:55.940516Z",
     "start_time": "2024-02-17T11:32:55.877645Z"
    },
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[  MainThread ]  0  :  青岛北\n",
      "[  MainThread ]  1  :  日照西\n",
      "[  MainThread ]  2  :  岚山西\n",
      "[  MainThread ]  3  :  赣榆\n",
      "[  MainThread ]  4  :  连云港\n",
      "[  MainThread ]  5  :  盐城\n",
      "[  MainThread ]  6  :  上海虹桥\n",
      "[  MainThread ] ------------------------\n",
      "[  MainThread ] | 当前时间 :  20:23:22  | \n",
      "[  MainThread ] ------------------------\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>上车站车次</th>\n",
       "      <th>起点站</th>\n",
       "      <th>补票站</th>\n",
       "      <th>车次</th>\n",
       "      <th>提前买</th>\n",
       "      <th>少买</th>\n",
       "      <th>提前买+少买</th>\n",
       "      <th>支出总时间/路程时间</th>\n",
       "      <th>无效时间比</th>\n",
       "      <th>站票时间(min)</th>\n",
       "      <th>二等座全程支出(元)</th>\n",
       "      <th>多余支出(元)</th>\n",
       "      <th>一等座余票量</th>\n",
       "      <th>二等座余票量</th>\n",
       "      <th>车次链接</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>D2145</td>\n",
       "      <td>青岛北</td>\n",
       "      <td>上海虹桥</td>\n",
       "      <td>D2145</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>304/199</td>\n",
       "      <td>1.527638</td>\n",
       "      <td>0</td>\n",
       "      <td>355</td>\n",
       "      <td>122</td>\n",
       "      <td>0</td>\n",
       "      <td>99</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=青岛北&amp;toCn=上海虹桥&amp;fromDate=2024-02-23#:~:text=D2145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>D2145</td>\n",
       "      <td>青岛北</td>\n",
       "      <td>盐城</td>\n",
       "      <td>D2145</td>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>4</td>\n",
       "      <td>304/199</td>\n",
       "      <td>1.527638</td>\n",
       "      <td>110</td>\n",
       "      <td>355</td>\n",
       "      <td>122</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=青岛北&amp;toCn=盐城&amp;fromDate=2024-02-23#:~:text=D2145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>D2145</td>\n",
       "      <td>青岛北</td>\n",
       "      <td>连云港</td>\n",
       "      <td>D2145</td>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>5</td>\n",
       "      <td>304/199</td>\n",
       "      <td>1.527638</td>\n",
       "      <td>182</td>\n",
       "      <td>355</td>\n",
       "      <td>122</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>https://www.suanya.com/pages/trainList?fromCn=青岛北&amp;toCn=连云港&amp;fromDate=2024-02-23#:~:text=D2145</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   上车站车次  起点站   补票站     车次  提前买  少买  提前买+少买 支出总时间/路程时间     无效时间比  站票时间(min)  \\\n",
       "0  D2145  青岛北  上海虹桥  D2145    3   0       3    304/199  1.527638          0   \n",
       "1  D2145  青岛北    盐城  D2145    3   1       4    304/199  1.527638        110   \n",
       "2  D2145  青岛北   连云港  D2145    3   2       5    304/199  1.527638        182   \n",
       "\n",
       "   二等座全程支出(元)  多余支出(元)  一等座余票量  二等座余票量  \\\n",
       "0         355      122       0      99   \n",
       "1         355      122       0       1   \n",
       "2         355      122       0       2   \n",
       "\n",
       "                                                                                            车次链接  \n",
       "0  https://www.suanya.com/pages/trainList?fromCn=青岛北&toCn=上海虹桥&fromDate=2024-02-23#:~:text=D2145  \n",
       "1    https://www.suanya.com/pages/trainList?fromCn=青岛北&toCn=盐城&fromDate=2024-02-23#:~:text=D2145  \n",
       "2   https://www.suanya.com/pages/trainList?fromCn=青岛北&toCn=连云港&fromDate=2024-02-23#:~:text=D2145  "
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 保留一等座余量或者二等座余量大于0的车次\n",
    "# 打印一下战列列表\n",
    "# item_stop_station_names\n",
    "for index, station_name in enumerate(item_stop_station_names):\n",
    "    print(\"\", index, \" : \", station_name)\n",
    "\n",
    "xlist_item_results_df_has_rest = xlist_item_results_df[\n",
    "    (xlist_item_results_df[\"一等座余票量\"] > 0)\n",
    "    | (xlist_item_results_df[\"二等座余票量\"] > 0)\n",
    "]\n",
    "# 遍历xlist_item_results 计算一下多买了少买了几站, 多买的基站, 基于station_start, 多买的站点, 基于station_end, 在xlist_item_results_df_has_rest增加两列显示\n",
    "# Get the indices of station_start and station_end in the item_stop_station_names list\n",
    "if len(xlist_item_results_df_has_rest) == 0:\n",
    "    throw(\"没有找到合适的车次\")\n",
    "\n",
    "start_station_index = item_stop_station_names.index(station_start)\n",
    "end_station_index = item_stop_station_names.index(station_end)\n",
    "\n",
    "# Calculate the number of extra stations bought based on station_start and station_end\n",
    "xlist_item_results_df_has_rest_buy_more_1 = xlist_item_results_df_has_rest[\n",
    "    \"起点站\"\n",
    "].apply(lambda x: start_station_index - item_stop_station_names.index(x))\n",
    "xlist_item_results_df_has_rest_buy_more_2 = xlist_item_results_df_has_rest[\n",
    "    \"终点站\"\n",
    "].apply(lambda x: end_station_index - item_stop_station_names.index(x))\n",
    "\n",
    "xlist_item_results_df_has_rest.insert(\n",
    "    5, \"提前买\", xlist_item_results_df_has_rest_buy_more_1\n",
    ")\n",
    "xlist_item_results_df_has_rest.insert(\n",
    "    6, \"少买\", xlist_item_results_df_has_rest_buy_more_2\n",
    ")\n",
    "# 提前买和少买的绝对值加合,增加一列\n",
    "xlist_item_results_df_has_rest.insert(\n",
    "    7,\n",
    "    \"提前买+少买\",\n",
    "    xlist_item_results_df_has_rest_buy_more_1.abs()\n",
    "    + xlist_item_results_df_has_rest_buy_more_2.abs(),\n",
    ")\n",
    "# 增加原始车次的结束时间\n",
    "xlist_item_results_df_has_rest.insert(9, \"原始车次结束时间\", train_item[\"EndTime\"])\n",
    "# 计算车次的时间区间和原始时间的重叠度,即当前车次的有效时间/原始需要的时间\n",
    "\n",
    "# 时间差值,需要字符串转换成时间\n",
    "from datetime import datetime\n",
    "\n",
    "# Convert strings to datetime objects\n",
    "train_item_start_time = datetime.strptime(train_item[\"StartTime\"], \"%H:%M\")\n",
    "train_item_end_time = datetime.strptime(train_item[\"EndTime\"], \"%H:%M\")\n",
    "train_time_diff = train_item_end_time - train_item_start_time\n",
    "train_time_diff_min = train_time_diff.total_seconds() / 60\n",
    "\n",
    "# 花钱的时间\n",
    "xlist_item_results_df_has_rest.insert(\n",
    "    10,\n",
    "    \"支出总时间\",\n",
    "    xlist_item_results_df_has_rest.apply(\n",
    "        lambda x: (\n",
    "            max(datetime.strptime(x[\"结束时间\"], \"%H:%M\"), train_item_end_time)\n",
    "            - datetime.strptime(x[\"开始时间\"], \"%H:%M\")\n",
    "        ).total_seconds()\n",
    "        / 60,\n",
    "        axis=1,\n",
    "    ),\n",
    ")\n",
    "# 花钱时间除以原始时间\n",
    "xlist_item_results_df_has_rest.insert(\n",
    "    11,\n",
    "    \"无效时间比\",\n",
    "    xlist_item_results_df_has_rest.apply(\n",
    "        lambda x: x[\"支出总时间\"] / train_time_diff_min, axis=1\n",
    "    ),\n",
    ")\n",
    "# 计算一下补票的时间,也就是需要站着的时间\n",
    "xlist_item_results_df_has_rest.insert(\n",
    "    12,\n",
    "    \"站票时间(min)\",\n",
    "    xlist_item_results_df_has_rest.apply(\n",
    "        lambda x: int(\n",
    "            (\n",
    "                train_item_end_time\n",
    "                - min(datetime.strptime(x[\"结束时间\"], \"%H:%M\"), train_item_end_time)\n",
    "            ).total_seconds()\n",
    "            / 60\n",
    "        ),\n",
    "        axis=1,\n",
    "    ),\n",
    ")\n",
    "\n",
    "xlist_item_results_df_has_rest.insert(\n",
    "    13,\n",
    "    \"二等座全程支出(元)\",\n",
    "    xlist_item_results_df_has_rest.apply(\n",
    "        lambda x: int(x[\"无效时间比\"] * train_item_second_price), axis=1\n",
    "    ),\n",
    ")\n",
    "xlist_item_results_df_has_rest.insert(\n",
    "    14,\n",
    "    \"多余支出(元)\",\n",
    "    xlist_item_results_df_has_rest.apply(\n",
    "        lambda x: int(x[\"二等座全程支出(元)\"] - train_item_second_price), axis=1\n",
    "    ),\n",
    ")\n",
    "xlist_item_results_df_has_rest.insert(\n",
    "    9,\n",
    "    \"支出总时间/路程时间\",\n",
    "    xlist_item_results_df_has_rest.apply(\n",
    "        lambda x: str(int(x[\"支出总时间\"])) + \"/\" + str(int(train_time_diff_min)),\n",
    "        axis=1,\n",
    "    ),\n",
    ")\n",
    "\n",
    "# 移除掉购买链接\n",
    "# xlist_item_results_df_has_rest = xlist_item_results_df_has_rest.drop(columns=[\"车次链接\"])\n",
    "xlist_item_results_df_has_rest = xlist_item_results_df_has_rest.drop(columns=[\"耗时\"])\n",
    "# xlist_item_results_df_has_rest = xlist_item_results_df_has_rest.drop(columns=[\"开始时间\"])\n",
    "xlist_item_results_df_has_rest = xlist_item_results_df_has_rest.drop(\n",
    "    columns=[\"结束时间\"]\n",
    ")\n",
    "xlist_item_results_df_has_rest = xlist_item_results_df_has_rest.drop(\n",
    "    columns=[\"一等座价格\"]\n",
    ")\n",
    "xlist_item_results_df_has_rest = xlist_item_results_df_has_rest.drop(\n",
    "    columns=[\"二等座价格\"]\n",
    ")\n",
    "xlist_item_results_df_has_rest = xlist_item_results_df_has_rest.drop(\n",
    "    columns=[\"原始车次结束时间\"]\n",
    ")\n",
    "xlist_item_results_df_has_rest = xlist_item_results_df_has_rest.drop(\n",
    "    columns=[\"开始时间\"]\n",
    ")\n",
    "xlist_item_results_df_has_rest = xlist_item_results_df_has_rest.drop(\n",
    "    columns=[\"支出总时间\"]\n",
    ")\n",
    "xlist_item_results_df_has_rest = xlist_item_results_df_has_rest.rename(\n",
    "    columns={\"终点站\": \"补票站\"}\n",
    ")\n",
    "xlist_item_results_df_has_rest = xlist_item_results_df_has_rest.rename(\n",
    "    columns={\"原始车次\": \"上车站车次\"}\n",
    ")\n",
    "\n",
    "xlist_item_results_df_has_rest = xlist_item_results_df_has_rest.sort_values(\n",
    "    by=[\"多余支出(元)\"], ascending=[True]\n",
    ")\n",
    "\n",
    "print(\"------------------------\")\n",
    "print(\"| 当前时间 : \", datetime.now().strftime(\"%H:%M:%S\"), \" | \")\n",
    "print(\"------------------------\")\n",
    "\n",
    "xlist_item_results_df_has_rest = xlist_item_results_df_has_rest.reset_index(drop=True)\n",
    "xlist_item_results_df_has_rest"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9bc7c3dd",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2024-02-17T11:32:55.930518Z"
    }
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
